home *** CD-ROM | disk | FTP | other *** search
Korn shell script | 1997-08-26 | 12.1 KB | 437 lines |
- #!/bin/ksh
- # @(#) dofiles.ksh 1.3 95/06/19
- # 94/11/22 john h. dubois iii (john@armory.com)
- # 94/12/04 Use nmv -i instead of mv if nmv is available. Added x option.
- # 95/01/02 Allow letters to be given in addtion to option numbers;
- # let parameters be given after options on the same line.
- # 95/04/11 Offer mail as an option if file is mailer text.
- # 95/04/29 Added [no] options; changed old n option to c.
- # 95/06/19 Added FBH! menu options.
-
- # Usage: uSelect prefix prompt-string word ...
- # uSelect presents the words in a select list.
- # If prefix is non-null, it is printed before the select list.
- # If prompt-string is null, a default prompt is used.
- # Each word must have at least one capital letter in it.
- # A word may be selected by number or by entering the first capital letter
- # in it (in upper or lower case). The letter (always capitalized) is returned
- # in the global var uSelect_ret. If more than one word is entered, the extra
- # words are returned in the global var uSelect_params.
- # If a word contains '|', the part before the '|' is used in the select list.
- # If no extra parameters are entered, then the part after the | is used as a
- # secondary prompt, and the words entered in response are assigned to
- # uSelect_params. The selection fails if no words are entered.
- # The entire selection selection string is returned in the global variable
- # uSelect_selected.
- # The return status is the number of the word selected (starting with 1),
- # or 0 if EOF or 'q' is entered.
- typeset -uL1 uSelect_ret
- function uSelect {
- typeset PS3 Cmd word letters= Prefix=$1 Options FullOpts
- typeset -uL1 l
- typeset -u U
- typeset -i CmdNum=1
-
- # Quit/help is not added as a regular menu item so that one more regular item
- # will fit on the screen. Instead, list it in prompt.
- [ -n "$2" ] && PS3=$2 ||
- PS3="Select by # or letter. Return for options, Q to quit: "
- shift 2
- set -A FullOpts -- "" "$@"
- for word; do
- Options[CmdNum]=${word%#*}
- l=${word##*([!A-Z])}
- letters=$letters$l
- let CmdNum+=1
- done
- print -u2 "\n$Prefix"
- select Cmd in "${Options[@]}"; do
- set -- $REPLY
- U=$1
- case "$U" in
- Q) # Quit
- return 0
- ;;
- !*) # Command to pass to shell
- ${REPLY#!}
- print -u2 "\n$Prefix"
- continue
- ;;
- esac
- # Do the elif test in two [[]] so that the one eval'ed is only done if
- # $REPLY is an upper-case letter
- if [ -n "$Cmd" ]; then
- CmdNum=$1
- # # If Quit option was selected by number...
- # [ CmdNum -gt ${#Options[*]} ] && return 0
- uSelect_ret=${Cmd##*([!A-Z])}
- elif [[ "$1" = [a-zA-Z] ]] && eval [[ "$letters" = "*$U*" ]]; then
- uSelect_ret=$U
- letters=${letters%%$U*}
- CmdNum=${#letters}+1
- else
- print -u2 "Invalid selection."
- print -u2 "\n$Prefix"
- continue
- fi
- shift
- uSelect_params="$*"
- word=${FullOpts[CmdNum]}
- if [[ -z "$uSelect_params" && "$word" = *#* ]]; then
- print -n -u2 "${word##*#} "
- read
- if [ -z "$REPLY" ]; then
- print -u2 "Must give a non-null response."
- print -u2 "\n$Prefix"
- continue
- fi
- uSelect_params=$REPLY
- fi
- uSelect_selected=${Options[CmdNum]}
- return $CmdNum
- done
- return 0
- }
-
- # Usage: DoFile filename
- function DoFile {
- typeset file=$1 Cmd dest conglomFile ExtraOptions f matches ftype info
- typeset Command
- typeset -i i=0
-
- if [ -n "$newer" -a ! "$file" -nt "$newer" ]; then
- print -u2 -- "$file is not newer than $newer; skipping."
- return 0
- fi
- if [ -n "$older" -a ! "$file" -ot "$older" ]; then
- print -u2 -- "$file is not older than $older; skipping."
- return 0
- fi
- if [ ! -a "$file" ]; then
- print -u2 -- "$file: No such file. Skipping."
- return 1
- fi
- if [ ! -f "$file" ]; then
- print -u2 -- "$file: Not a regular file. Skipping."
- return 1
- fi
- if [ ${#rmFiles[*]} -gt 0 ]; then
- ExtraOptions[i]="delete files currently marKed"
- let i+=1
- ExtraOptions[i]="select files to Unmark"
- let i+=1
- fi
- if $FileDone; then
- ExtraOptions[i]="view file Status"
- let i+=1
- fi
- if $conglomFound; then
- ExtraOptions[i]="Conglomerate onto a specified file#Conglomerate onto:"
- let i+=1
- fi
- if $conglom; then
- conglom -l "$file" | read f matches
- for f in $matches; do
- ExtraOptions[i]="conglomerate Onto $f"
- let i+=1
- done
- fi
-
- set -- $(file $file)
- shift
- ftype="$*"
- if [[ "$ftype" = *mail* ]]; then
- ExtraOptions[i]="read file into mAiler"
- let i+=1
- fi
-
- info=$(l -- "$file")
-
- while :; do
-
- uSelect \
- "Current file: $file
- File type: $ftype
- $info" \
- "" \
- "View" \
- "Edit" \
- "Move#Move to:" \
- "Forward file via email#Mail to:" \
- "uuencode Binary file & email it#Mail to:" \
- "Run a command on the file#Command:" \
- "mark for Deletion" \
- "Go on to next file" \
- "print Help" \
- "${ExtraOptions[@]}" && Finish
- # Possible ExtraOptions: Delete marked, select to Unmark, view Status,
- # Conglomerate, conglomerate Onto, read file into mAiler. Q used by Quit.
- # A B C D E F G H K M O Q R S U V
-
- $debug && set -x
- case "$uSelect_ret" in
- A) # Run file into mailer
- mail -f "$file"
- ;;
- B) # uuencode Binary file & email it
- uuencode "$file" "$file" |
- mail -s "File transfer ($file), uuencoded" $uSelect_params
- ;;
- C) # Conglomerate
- dest=$uSelect_params
- if [ -n "$dest" ] && conglom -- "$file" "$dest"; then
- FilesConglomerated="$FilesConglomerated $file"
- break
- fi
- ;;
- F) # Forward file via email
- mail -s "File transfer ($file)" $uSelect_params <"$file"
- ;;
- K) # Delete marked files
- FilesRemoved="$FilesRemoved ${rmFiles[*]}"
- print "Removing: ${rmFiles[*]}"
- rm -- "${rmFiles[@]}"
- unset rmFiles[*]
- break
- ;;
- E) # Edit
- "$VISUAL" "$file";;
- G) # Go on to next file
- FilesUntouched="$FilesUntouched $file"
- break
- ;;
- H) # print Help
- print -- \
- "Options (in the following, the parameter referred to can be given after the
- command; if it is not, it will be queried for):
- A invokes the standard mailer on the file.
- B and F send the file by mail to the destination given by the parameter.
- If B is used, the file is uuencoded first. The subject is set to 'File
- transfer (filename)' for F and 'File transfer (filename), uuencoded' for B.
- C and O conglomerate the file (append it to another file and then remove it).
- C takes the target file as the parameter; O offers a specific list of files.
- D marks the file for deletion. It will be deleted when the K command is given,
- or if the option to remove all marked files is used when $name is quit.
- E runs the editor on the file. The editor is given by the environment variable
- VISUAL; or if not set, the variable EDITOR; or if not set, the \"vi\" editor.
- G skips the file (no action is taken on it).
- K immediately deletes any files that have been marked for deletion.
- M moves the file to the new name given by the parameter.
- R passes the file as an argument to the command given by the parameter.
- S shows file status; it reports which file have been moved, removed, marked for
- removal, conglomerated onto others, and left alone.
- U allows files that have been marked for removal to be unmarked.
- V views the file using a pager. The pager is given by the environment variable
- PAGER; or if it is not set, the standard pager \"more\".
- !command runs command with any arguments and then returns to the menu."
- print -n "Press return to continue..."
- read
- ;;
- D) # Mark for deletion
- rmFiles[${#rmFiles[*]}]=$file
- break
- ;;
- M) # Move
- dest=$uSelect_params
- if [ -n "$dest" ] && $mv -- "$file" "$dest"; then
- FilesMoved="$FilesMoved $file"
- break
- fi
- ;;
- O) # Conglomerate onto
- set -- $uSelect_selected
- if conglom -- "$file" "$3"; then
- FilesConglomerated="$FilesConglomerated $file"
- break
- fi
- ;;
- R) # Run a command on file
- $uSelect_params "$file"
- ;;
- S) # View file status
- print \
- "Files moved: $FilesMoved
-
- Files removed: $FilesRemoved
-
- Files marked for removal: ${rmFiles[*]}
-
- Files conglomerated onto others: $FilesConglomerated
-
- Files left alone: $FilesUntouched"
- ;;
- U) # Select files to unmark
- UnselectFiles
- ;;
- V) # View file
- ${PAGER:-more} "$file";;
- esac
- $debug && set +x
- done
- FileDone=true
- return 0
- }
-
- function UnselectFiles {
- typeset file
- typeset -i filenum
-
- # Must have an outer loop so file list is rebuilt when a file is unmarked
- while :; do
- print \
- "These files are marked for removal.
- Enter the number of one to unmark, or r to return to the previous menu."
- select file in "${rmFiles[@]}"; do
- [[ "$REPLY" = [rR] ]] && return
- if [ -n "$file" ]; then
- let filenum=REPLY-1
- # Print this insteead of $file to make it obvious if something
- # goes wrong
- print "Unmarking: ${rmFiles[filenum]}"
- unset rmFiles[filenum]
- # normalize indices
- set -A rmFiles -- "${rmFiles[@]}"
- if [ ${#rmFiles[*]} -eq 0 ]; then
- print "All files unmarked."
- return
- fi
- break
- fi
- done
- done
- }
-
- function Finish {
- typeset answer
-
- if [ ${#rmFiles[*]} -eq 0 ]; then
- print -u2 "No files marked for removal."
- exit 0
- fi
- print \
- "Files marked for removal: ${rmFiles[*]}
- Select an option by number:"
- select answer in \
- "Remove all marked files" \
- "Do not remove any files" \
- "Select files to unmark"
- do
- case "$answer" in
- Remove*)
- print "Removing: ${rmFiles[*]}"
- rm -- "${rmFiles[@]}"; break;;
- Do*)
- break;;
- Select*)
- UnselectFiles;;
- esac
- [ ${#rmFiles[*]} -eq 0 ] && break
- done
- exit 0
- }
-
- type conglom > /dev/null && conglomFound=true || conglomFound=false
- [ -f "${CGFILES:-$HOME/.files}" ] && $conglomFound &&
- conglom=true || conglom=false
- debug=false
- FileDone=false
-
-
- [ -z "$VISUAL" ] && VISUAL=${EDITOR:-vi}
-
- name=${0##*/}
- Usage="Usage: $name [-hc] [-n<file>] [-o<file>] file ..."
-
- while getopts :hicxn:o: opt; do
- case $opt in
- h)
- echo \
- "$name: deal with files.
- $name takes a list of files and for each one gives a list of options for what
- may be done with it. If no filenames are given on the command line, they are
- read from the standard input, one per line. The options are:
- View: the file is passed to a pager.
- Edit: the file is passed to an editor.
- Move: a new name is queried for, and the file is moved to it.
- Run a command on the file: a command line is queried for, and is run with the
- filename appended to it.
- Mark for removal: the file is added to a list of files to be removed.
- Conglomerate onto another file: ask for another filename and append the
- contents of this file to it; then remove the original file.
- Go on to next file: do not do anything to the file.
- Remove files currently marked: immediately removed the marked files.
- View file status: list what has been done with each file processed so far.
- Quit: ask whether marked files should be removed; if the answer is yes,
- remove then; then quit.
- If the 'conglom' utility finds matches for the file, conglomeration onto
- specific files is also offered.
- $Usage
- Options:
- -h: Print this help.
- -c: Do not offer a list of files that the file may be conglomerated onto
- as an option. This avoid running 'conglom' for each file to find matches.
- -n<file>: Process only files newer (more recently modified) than <file>.
- -o<file>: Process only files older (less recently modified) than <file>."
- exit 0
- ;;
- c)
- conglom=false
- ;;
- n)
- newer=$OPTARG
- if [ ! -a "$newer" ]; then
- print -u2 -- "$newer: no such file."
- exit 1
- fi
- ;;
- o)
- older=$OPTARG
- if [ ! -a "$older" ]; then
- print -u2 -- "$older: no such file."
- exit 1
- fi
- ;;
- x)
- debug=true
- ;;
- +?)
- print -u2 "$name: options should not be preceded by a '+'."
- exit 1
- ;;
- :)
- print -r -u2 -- \
- "$name: Option '$OPTARG' requires a value. Use -h for help."
- exit 1
- ;;
- ?)
- print -u2 "$name: $OPTARG: bad option. Use -h for help."
- exit 1
- ;;
- esac
- done
-
- # remove args that were options
- let OPTIND=OPTIND-1
- shift $OPTIND
-
- # nmv is more careful above moves
- if type nmv > /dev/null; then
- mv='nmv -i'
- $debug && print -u2 'Using nmv -i instead of mv'
- else
- mv=mv
- fi
-
- if [ $# -lt 1 ]; then
- # If reading file list, use /dev/tty for user input
- while read file; do
- DoFile "$file" < /dev/tty
- done
- else
- for file; do
- DoFile "$file"
- done
- fi
-
- [ ${#rmFiles[*]} -ne 0 ] && Finish
-